#ifndef __BTMSGHANDLER_H__
#define __BTMSGHANDLER_H__
/*
 * 接收来自设备端的数据，必须串行，接收一个完整包（可以是中间包）后，可以穿插ack包,
 * 如果收到包起始字节，即使在一个包接收的中途，也尝试判断是否合法的包头（检查前9个字节）,如果是合法包头，则舍弃之前的数据。
 */
#include "btinterface.h"
#include <list>
#include <thread>
#include <queue>
#include <miniglog/logging.h>

#define SW_VER_STR "[v12] "
//#define DIRECT_TRANS_BLE //透传模式（不等待ack）

//接收状态
#define LT_RECV_ST_NONE 0
#define LT_RECV_ST_RCV 1
#define LT_RECV_ST_ACK 2

#define LT_PKG_LEN 500 //最大包长度
#define LT_ACK_PKG_LEN 12 //ack包长度，也是最小包长度
#define LT_MIN_PKG_LEN LT_ACK_PKG_LEN
#define LT_PKG_HEAD_LEN 9
#define LT_PKG_TAIL_LEN 2
#define LT_BGBYTE       ((unsigned char)170) //  AA
#define LT_BGBYTE_ACK   ((unsigned char)187)// BB
#define LT_ENDBYTE      ((unsigned char)102)// 0x66
#define LT_ENDBYTE_LAST ((unsigned char)85)// 0x55

//数据包头定义
class CLtPkgHeader
{
public:
    CLtPkgHeader()
    {
        headByte=0;
        pkgLen=0;
        taskId=0;
        storeId=0;
        pkgSum=0;
        pkgSeq=0;
    }
    unsigned char headByte;//0xAA 普通recv包， 0xBB 设备端ack包
    unsigned short pkgLen;
    unsigned char taskId;
    unsigned char storeId;
    unsigned short pkgSum;
    unsigned short pkgSeq;
    bool init(const unsigned char* pData, int dataLen);
    static bool isValidHead(const unsigned char* pData, int dataLen);//只检查前9个字节（包头）
    static bool isValidPkgSt(const unsigned char* pData, int dataLen);
    bool isValidPkg(const unsigned char* pData, int dataLen);
    static bool isValidAckPkg(const unsigned char* pData, int dataLen);
    static bool isPkgReceived(const unsigned char* pData, int dataLen);
    static int skip(unsigned char* pData, int &dataLen);
    bool isLastPkg()
    {
        return pkgSeq+1==pkgSum;
    }
     bool isAckPkg()
    {
        return isAckPkg(this->headByte);
    }
    static bool isAckPkg(unsigned char headerByte)
    {
        return headerByte==LT_BGBYTE_ACK;
    }
    static bool isRcvPkg(unsigned char headerByte)
    {
        return headerByte==LT_BGBYTE;
    }
    static bool isHeadReceived(int dataLen)
    {
        return dataLen>=LT_PKG_HEAD_LEN;
    }
    static bool isAckPkgReceived(int dataLen)
    {
        return dataLen>=LT_ACK_PKG_LEN;
    }
    static bool isValidTaskId(unsigned char tid){
        return tid==1 || tid==2 || tid==3;
    }
};
class CLtRecvPackage
{
public:
    CLtRecvPackage()
    {
        init();
    }
    CLtRecvPackage(const unsigned char* pData, int dataLen)
    {
        init();
        addData(pData, dataLen);
    }
    virtual ~CLtRecvPackage()
    {
        clear();
    }
    int addData(const unsigned char* pData, int dataLen);
    bool isValidRcvPkg();
    void skip();
    void init()
    {
        m_pData=NULL;
        m_dataSize=0;
        m_dataLen=0;
        //m_lastAApos=-1;
        m_isHeadOk=false;
        m_isPkgOk=false;
        m_bSkipToAck=false;
        m_bSkipToGoodRcv=false;
    }
    bool isValidHead()
    {
        return CLtPkgHeader::isValidHead(m_pData, m_dataLen);
    }

    void clear()
    {
        if(NULL!=m_pData)
        {
            delete[] m_pData;
        }
        init();
    }
    unsigned char * getBusinessData(){
        if(NULL==m_pData){
            return NULL;
        }
        return m_pData+LT_PKG_HEAD_LEN;
    }
    unsigned short getBusinessDataLen(){
        if(m_dataLen>LT_PKG_HEAD_LEN+2){
            return m_dataLen-(LT_PKG_HEAD_LEN+2);
        }
        return (unsigned short)0;
    }
    bool isHeadReceived(){
        return NULL!=m_pData && CLtPkgHeader::isHeadReceived(m_dataLen);
    }
    unsigned short calcPkgLength(const unsigned char* pData, int dataLen);
    CLtPkgHeader m_header;
    unsigned char * m_pData;
    bool m_isHeadOk;
    bool m_isPkgOk;//整包接收完毕，并且校验通过
    bool m_bSkipToAck;
    bool m_bSkipToGoodRcv;
    int m_dataSize;//如果是recv包，先分配500，如果不足，再扩大。如果是ack包，数据部分只有1个字节。
    int m_dataLen;
    //int m_lastAApos;//可能是下一个包头的字节位置，一旦后面接收到足够长度数据，就判断是否包头，如果是包头则删除前面数据（废数据）
};
class CLtAckPackage
{
public:
    CLtAckPackage()
    {
        m_bufLen=0;
        m_data=0;
    }
    CLtPkgHeader m_header;
    unsigned char m_buf[LT_ACK_PKG_LEN];
    int m_bufLen;
    unsigned char m_data;
    int init(const unsigned char* pData, int dataLen);
    int init()
    {
        return init(m_buf, m_bufLen);
    }
    void clear()
    {
        m_bufLen=0;
    }
    bool isAckSuccess()
    {
        return 0x01==m_data;
    }
    int appendToBuf(const unsigned char* pData, int dataLen)
    {
        int i,j;
        LOG(INFO) << "CAckPkg,appendToBuf m_bufLen="<<m_bufLen;
        for(i=m_bufLen,j=0;j<dataLen&&i<LT_ACK_PKG_LEN;++i,++j){
            m_buf[i]=pData[j];
        }
        m_bufLen=i;
        return j;//追加的长度
    }
    void skip(bool & isRcvPkg){
        isRcvPkg=false;
        int flag=CLtPkgHeader::skip(m_buf, m_bufLen);
        if(flag==1){
            isRcvPkg=true;
        }
//        if(m_bufLen<=0){
//            return;
//        }
//        int i;
//        for( i=1;i<m_bufLen;++i){
//            if(LT_BGBYTE_ACK==m_buf[i])
//                break;
//            if(LT_BGBYTE==m_buf[i]){
//                isRcvPkg=true;
//                break;
//            }
//        }
//        int k;
//        for( k=0; k<m_bufLen-1 && i<m_bufLen; ++k,++i){
//            m_buf[k]=m_buf[i];
//        }
//        m_bufLen=k;
    }
};

class BtSdkListener: public IBtSdkListener
{
    void onRecvBleData(const unsigned char* businessData,  const DataInfo* dataInfo);
    void sendToBaseBle(const unsigned char* basePkg, int pkgLen);
    void onSendDataResult(int retCode, int dataLen, char taskId, char storeId);
};

class BtMsghandler: public IBtSdkInterface
{
#define TO_TRESMITT_RECVRESPOND 2000    // 从准备发送1级包到接收应答包的时间, 单位毫秒
#define PACKAGE_SIZE            500
#define LT_BLE_SIZE         53 //单包大小 MTU 目标值   (SUBPACKAGE_SIZE=LT_BLE_SIZE-3)
#define LT_BLE_SIZE_DEF         23 //单包大小 MTU 缺省值
#define PACKAGE_SEND_DELAY  15  //二级包发送间隔 ms(缺省值)
#define RE_SEND_MAX_CNT 5 //大包重发最大次数
public:
    BtMsghandler();
    ~BtMsghandler();

private:
    IBtSdkListener *m_pListener;
    std::list<unsigned char*> m_sendList;
    const unsigned char *m_pSendData;
    std::thread *m_thread;
    std::thread *m_threadRecv;
    std::mutex m_mutex;
    std::mutex m_mutexSndBleRlt;
    std::mutex m_mutexBSndBleRltGot;
    std::mutex m_mutexSending;
    std::mutex m_mutexBleDevAckGot;
    std::mutex m_mutexRecvList;
    std::mutex m_mutexRecvListNotify;
    std::unique_lock<std::mutex> *m_lck;
    std::unique_lock<std::mutex> *m_lckSndBleRlt;
    std::unique_lock<std::mutex> *m_lckRecvList;
    std::condition_variable m_cv;
    std::condition_variable m_cvSndBleRlt;
    std::condition_variable m_cvRecvList;
    int m_sndBleRlt;
    bool m_bBleDevAckGot;//是否已得到大包的设备端ack结果
    bool m_bSndBleRltGot;//是否已得到最新发送结果，true表示有硬件层返回的最新发送结果result
    bool m_exitSendThread;
    bool m_bIndict_OK;                 // 设备应答指示接收到的数据包（一级包）正确与否
    bool m_bSending;//发送标志，必须通过函数访问（加锁互斥）
    int m_reSendCnt=0;

    std::list<CLtRecvPackage*> m_recvPkgList;
    int m_recvPkgListCount;
    int m_recvState;//0 nodata, 1 recv, 2 ack
    CLtRecvPackage* m_pRecvPkg;
    CLtAckPackage   m_ackPkg;
private:
    short m_noRecvPacket;   // 包顺序号
    short m_lenRecvPacket; // 数据长度
    unsigned char m_idRecvTask;     // 任务标识
    unsigned char m_idRecvStore;    // 药仓编号
    short m_sumRecvPacket;  // 任务总包数
    short m_seqRecvPacket;  // 包顺序号
    unsigned char m_checkRecvPacket;    // 校验位
    int m_mtu;
    int m_pkgDelayMs;

    int m_DataPos;             // 接收数据缓冲区的位置指针
    int m_DataLastPos;         // 指向接收数据缓冲区的上次位置
    short m_posRecvPacket;     // 从0XAA算起，处理字节的个数
    unsigned char *m_pRecvData;             // 指向接收缓冲区
    bool m_bErrReport;
    bool m_bRespondPacket;         // true 回应包， false
    unsigned char m_RespondOK;              // 回应包OK
    unsigned char m_Endbyte;

    typedef enum
    {
        S0_Recv = 0,    // 初始状态，复位m_noPacket, m_checkRecvPacket
        S_RecvN0Packet,   // 接收每个一级包的第一个二级包
        S_RecvNnPacket,                  // 接收除了第一个二级小包后的二级包
        S_RecvFinish,                 // 完成一整个一级包的接收
        S_RecvErr

    }E_RECV_STA;
    E_RECV_STA recv_sta;

public:
    void setListener(IBtSdkListener* listener){m_pListener  = listener;}
    void handleBaseBlePackage(const unsigned char* data, const int dataLen);
    int sendData(const unsigned char* businessData, const DataInfo *dataInfo);
    int getMTU();
    int getNewMTU();
    int getNewMTUAct();//实际可用mtu（去掉3字节系统数据）
    void setNewMTU(int newMTU);
    void setPkgDelay(int delayMs);
    void onNotifySendToBaseBleResult(int result);
    bool isSending();
private:
    void setSending(bool b);
    void doStopSend(int retCode, int dataLen, char taskId, char storeId);//retCode 0发送成功，1服务端回应发送失败，2发送超时，3本地发送失败, 100线程停止
    bool checkEnd(const unsigned char data);
    void makeReponseCode(unsigned char *pReponseCode, char isOK);
    void makesubPacketandSendTask();
    void threadRecvBle();
    void Respond_handle(bool bOk);
    void clrSendList();
    void handleSubPackage(const unsigned char **ppData, int *len);
    void handleFirstPackage(const unsigned char **ppData, int* len);
    int handleRecvBleData(const unsigned char* data, int  dataLen);
    int readAckPkg(const unsigned char *data, int dataLen);
    int readRcvPkg(const unsigned char *data, int dataLen);
    void createNewRcvPkg(const unsigned char* data, int  dataLen);
    void addToRecvList(CLtRecvPackage* pPkg);
    CLtRecvPackage* getLastRecvPkg(int & pkgCnt);
    int getPkgDelay();

    int waitForBleDevAck();
    int waitForSendBaseBleResult();
    void setBleDevAckGot(bool b);
    void setSndBleRltGot(bool b);
    bool isBleDevAckGot();
    bool isSndBleRltGot();
    bool isRecvStateRcv();
    bool isRecvStateAck();
    bool isRecvStateNone();
    void setRecvState(int state);

    void resetReSendCnt();
    bool canReSend(bool useOneCnt=false);
};



#endif // __BTMSGHANDLER_H__
